import json
from datetime import datetime  # 处理日期和时间的标准库

from django.core.paginator import Paginator  # 管理分页数据
from django.http import JsonResponse  # 用于返回 JSON 格式数据
# from django.shortcuts import render
from django.views import View  # Django的视图基类
from rest_framework_jwt.settings import api_settings  # JWT配置
from rest_framework_jwt.utils import jwt_payload_handler  # 生成JWT载荷

from djangoProject import settings
from menu.models import SysMenu, SysMenuSerializer  # 菜单表和序列化器
from role.models import SysRole, SysUserRole  # 角色表
from user.models import SysUser, SysUserSerializer  # 用户表和序列化器


# 接口的开发方式尽可能的去遵循 Restful 规范


# 测试Token有效性，返回所有用户数据
class TestView(View):
    # 处理GET请求（测试权限）
    def get(self, request):
        token = request.META.get('HTTP_AUTHORIZATION')  # 从请求头获取Token

        # 如果有Token
        if token != None and token != '':
            # 通过调用all()方法，返回QuerySet类型的对象数据集
            userList_obj = SysUser.objects.all()  # 返回所有用户信息
            # print(userList_obj, type(userList_obj))

            # 通过values方法转成字典类型数据集
            userList_dict = userList_obj.values()  # 转存字典
            # print(userList_dict, type(userList_dict))

            # 通过list方法，转成List集合，再返回给前端。否则会出现序列化报错问题
            useList = list(userList_dict)
            # print(useList, type(useList))

            return JsonResponse(
                {'code': 200, 'info': '测试！', 'data': useList},
                json_dumps_params={'ensure_ascii': False})  # 关闭 ASCII 转义

        else:
            # 无Token，拒绝访问
            return JsonResponse(
                {'code': 401, 'info': '没有访问权限！'},
                json_dumps_params={'ensure_ascii': False})  # 关闭 ASCII 转义


# 生成测试用Token
class JwtTestView(View):
    # 生成测试用的Token
    def get(self, request):
        # 查找指定用户
        user = SysUser.objects.get(username='root', password='m,./')

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        # 生成Token
        # 将用户对象传递进去，获取到该对象的属性值
        payload = jwt_payload_handler(user)
        # 将属性值编码成jwt格式的字符串
        token = jwt_encode_handler(payload)
        return JsonResponse({'code': 200, 'token': token})


# 用户登录后，返回权限信息和菜单结构
class LoginView(View):
    # 处理POST请求（用户提交登录表单）
    def post(self, request):
        # 用户输入账号密码后，从请求参数中获取用户名和密码
        username = request.GET.get('username')
        password = request.GET.get('password')  # 实际应用中，须用POST传递密码！
        try:
            # 数据库核对账号密码，验证用户是否存在
            user = SysUser.objects.get(username=username, password=password)
            # 生成JWT Token（类似“临时通行证”）
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)  # # 将用户对象传递进去，获取到该对象的属性值
            token = jwt_encode_handler(payload)  # 将属性值编码成jwt格式的加密字符串

            # 查询用户拥有的角色比如管理员、普通用户）
            roleList = SysRole.objects.raw(
                "SELECT id ,NAME FROM sys_role WHERE id IN (SELECT role_id FROM sys_user_role WHERE user_id=" + str(
                    user.id) + ")")
            # print(roleList)

            # 将当前用户所有的角色，拼接成字符串，逗号隔开
            roles = ",".join([role.name for role in roleList])

            # 查询这些角色能访问的菜单（比如用户管理、订单管理）
            menuSet: set[SysMenu] = set()  # 用集合去重
            for row in roleList:
                # print(row.id, row.name)
                menuList = SysMenu.objects.raw(
                    "SELECT * FROM sys_menu WHERE id IN (SELECT menu_id FROM sys_role_menu WHERE role_id=" + str(
                        row.id) + ")")
                for row2 in menuList:
                    # print(row2.id, row2.name)
                    menuSet.add(row2)  # 将菜单加入集合
            # print(menuSet)

            menuList: list[SysMenu] = list(menuSet)  # set转list
            sorted_menuList = sorted(menuList)  # 根据数据库中的order_num，对菜单按顺序排序
            # print(sorted_menuList)

            # 构造菜单树 将菜单组织成树形结构（父子层级）
            sysMenuList: list[SysMenu] = self.buildTreeMenu(sorted_menuList)
            # print(sysMenuList)

            serializerMenuList = list()  # 将菜单数据转换为JSON格式
            for sysMenu in sysMenuList:
                serializerMenuList.append(SysMenuSerializer(sysMenu).data)

        except Exception as e:
            # print(e)
            # 登录失败，返回错误信息
            return JsonResponse({'code': 500, 'info': '用户名或密码错误!'})

        # 登录成功，返回Token、用户信息和菜单
        return JsonResponse({'code': 200,
                             'token': token,
                             'user': SysUserSerializer(user).data,
                             'info': '登陆成功!',
                             'roles': roles,
                             'menuList': serializerMenuList})

    def buildTreeMenu(self, sysMenuList):
        # 存储最终树形菜单
        resultMenuList: list[SysMenu] = list()

        for menu in sysMenuList:
            # 寻找子节点(寻找当前菜单的子菜单)
            for e in sysMenuList:
                if e.parent_id == menu.id:
                    if not hasattr(menu, "children"):
                        menu.children = list()  # 创建子菜单列表
                    menu.children.append(e)

            # 判断父节点，如果是顶级菜单（没有父菜单），加入结果列表
            if menu.parent_id == 0:
                resultMenuList.append(menu)
        return resultMenuList


# 新增/修改用户
class SaveView(View):
    def post(self, request):
        data = json.loads(request.body.decode('utf-8'))  # 解析请求数据
        # print(data)
        if data['id'] == -1:  # 是新增用户
            # 创建新用户对象，设置默认密码、创建时间、头像
            obj_sysUser = SysUser(username=data['username'],
                                  password=data['password'],
                                  email=data['email'],
                                  phonenumber=data['phonenumber'],
                                  status=data['status'],
                                  remark=data['remark'])

            obj_sysUser.create_time = datetime.now().date()
            obj_sysUser.avatar = 'default.jpg'
            obj_sysUser.password = "123456"
            obj_sysUser.save()  # 保存到数据库
        else:
            # 根据ID找到老用户，更新信息，记录修改时间
            obj_sysUser = SysUser(id=data['id'],
                                  username=data['username'],
                                  password=data['password'],
                                  avatar=data['avatar'],
                                  email=data['email'],
                                  phonenumber=data['phonenumber'],
                                  login_date=data['login_date'],
                                  status=data['status'],
                                  create_time=data['create_time'],
                                  update_time=data['update_time'],
                                  remark=data['remark'])

            obj_sysUser.update_time = datetime.now().date()
            obj_sysUser.save()

        return JsonResponse({'code': 200, 'info': '登陆成功!'})


# 修改密码
class PwdView(View):
    # 当用户提交修改密码请求时触发
    def post(self, request):

        data = json.loads(request.body.decode("utf-8"))  # 解析用户提交的数据
        id = data['id']  # 用户ID
        oldPassword = data['oldPassword']  # 旧密码
        newPassword = data['newPassword']  # 新密码

        obj_user = SysUser.objects.get(id=id)  # 根据用户ID,去数据库找到对应的用户

        # 验证旧密码
        if obj_user.password == oldPassword:  # 如果旧密码正确

            obj_user.password = newPassword  # 设置新密码
            obj_user.update_time = datetime.now().date()  # 记录修改时间
            obj_user.save()  # 保存到数据库
            return JsonResponse({'code': 200})  # 传递信息至前端
        else:
            return JsonResponse({'code': 500, 'errorInfo': '原密码错误！'})


# 上传头像
class ImageView(View):
    # 当用户上传头像时触发
    def post(self, request):

        file = request.FILES.get('avatar')  # 从前端请求中获取头像文件
        # print("file:", file)

        if file:  # 如果有文件
            file_name = file.name  # 给文件起个名（避免重复）
            suffixName = file_name[file_name.rfind("."):]  # 截取后缀（比如".jpg"）

            # 生成新名字（如"20251001123045.jpg"）
            new_file_name = datetime.now().strftime('%Y%m%d%H%M%S') + suffixName
            # 确定保存路径
            file_path = str(settings.MEDIA_ROOT) + "\\userAvatar\\" + new_file_name
            # print("file_path:", file_path)

            try:
                # 打开文件准备写入
                with open(file_path, 'wb') as f:
                    for chunk in file.chunks():  # 分块读取文件内容（避免大文件卡死）
                        f.write(chunk)  # 写入到指定路径
                return JsonResponse({'code': 200, 'title': new_file_name})
            except:
                return JsonResponse({'code': 500, 'errorInfo': '上传头像失败'})


# 更新头像路径
class AvatarView(View):
    # 当用户确认使用新头像时触发
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))  # 获取前端发来的数据

        id = data['id']  # 用户ID（xx的头像）
        avatar = data['avatar']  # 头像文件名（xx.jpg）
        obj_user = SysUser.objects.get(id=id)  # 根据用户ID,去数据库找到对应的用户

        # 更新头像路径,把头像文件名存到用户信息里
        obj_user.avatar = avatar
        obj_user.save()  # 保存到数据库
        return JsonResponse({'code': 200})


# 分页搜索用户
class SearchView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))  # 获取前端发来的数据
        pageNum = data['pageNum']  # 当前页
        pageSize = data['pageSize']  # 每页大小
        query = data['query']  # 查询参数
        # print(pageNum, pageSize, query)

        # 根据关键词模糊搜索用户名,分页处理（比如每页显示10条）
        userListPage = Paginator(SysUser.objects.filter(username__icontains=query),
                                 pageSize).page(pageNum)
        # print(userListPage)

        users = list(userListPage.object_list.values())
        # print(users)

        for user in users:  # 查询每个用户的角色信息
            userId = user['id']
            roleList = SysRole.objects.raw(
                "SELECT id,NAME FROM sys_role WHERE id IN(SELECT role_id FROM sys_user_role WHERE user_id =" + str(
                    userId) + ")")
            roleListDict = []
            for role in roleList:
                roleDict = {}
                roleDict['id'] = role.id
                roleDict['name'] = role.name
                roleListDict.append(roleDict)
            user['roleList'] = roleListDict
        total = SysUser.objects.filter(username__icontains=query).count()
        return JsonResponse({'code': 200, 'userList': users, 'total': total})


# 查看用户详细信息或删除用户（连带清理权限）
class ActionView(View):
    # 根据ID查单个用户详情
    def get(self, request):
        id = request.GET.get("id")
        user_object = SysUser.objects.get(id=id)
        return JsonResponse({'code': 200,
                             'user': SysUserSerializer(user_object).data})

    # 批量删除用户，同时删除关联的角色权限
    def delete(self, request):
        idList = json.loads(request.body.decode("utf-8"))
        SysUserRole.objects.filter(user_id__in=idList).delete()
        SysUser.objects.filter(id__in=idList).delete()
        return JsonResponse({'code': 200})


# 检查用户名是否重复
class CheckView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        username = data['username']
        # print("username=", username)
        # 检查数据库是否存在该用户名
        if SysUser.objects.filter(username=username).exists():
            return JsonResponse({'code': 500})
        else:
            return JsonResponse({'code': 200})


# 重置密码
class PasswordView(View):
    def get(self, request):
        id = request.GET.get("id")
        user_object = SysUser.objects.get(id=id)
        # 将指定用户的密码重置为123456
        user_object.password = "123456"
        # 记录修改时间
        user_object.update_time = datetime.now().date()
        user_object.save()
        return JsonResponse({'code': 200})


# 用户状态修改
class StatusView(View):
    # 启用或禁用用户（1正常，0禁用）
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        id = data['id']
        status = data['status']
        user_object = SysUser.objects.get(id=id)
        user_object.status = status
        user_object.save()
        return JsonResponse({'code': 200})


# 给用户分配权限组（如从“普通用户”改为“管理员”）
class GrantRole(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        user_id = data['id']
        roleIdList = data['roleIds']
        # print(user_id, roleIdList)

        SysUserRole.objects.filter(user_id=user_id).delete()  # 删除用户角色关联表中的指定用户数据
        for roleId in roleIdList:
            userRole = SysUserRole(user_id=user_id, role_id=roleId)
            userRole.save()
        return JsonResponse({'code': 200})
